DynamoDBのORM「PynamoDB」を使ってみる
PynamoDB
PynamoDBはDynamoDBのPython用クライアントです。
SQLAlchemyなどのORMのようにDynamoDBを操作することができます。
Boto3などを使ってDynamoDBを操作していると、dict
⇄データクラスの変換が発生してコードが冗長になる気がします。
また、dict
型だとインテリセンスの問題もあります。クラスになっているとその辺りは楽になる気がします。
インストール
pipでインストール可能です
pip3 install pynamodb
使ってみる
テーブルの定義
from pynamodb.models import Model from pynamodb.attributes import UnicodeAttribute, NumberAttribute class User(Model): class Meta: table_name = "User" region = 'ap-northeast-1' read_capacity_units = 1 write_capacity_units = 1 name = UnicodeAttribute(hash_key=True) email = UnicodeAttribute(range_key=True) age = NumberAttribute(null=True)
テーブルのデータモデルを定義しています。
内部クラスのMeta
にはテーブルの設定を書くことができます。
今回はUser
というテーブルを作成しています。
name
をパーティションキーにして、email
をソートキーにしています。
age
は単なるAttributeです。
Attributeとして使えるのは以下のものです。
- UnicodeAttribute
- UnicodeSetAttribute
- NumberAttribute
- NumberSetAttribute
- BinaryAttribute
- BinarySetAttribute
- UTCDateTimeAttribute
- BooleanAttribute
- JSONAttribute
- MapAttribute
UTCDateTimeなどがあるのは便利です。シリアライズの手間が省けます。
自分でAttributeを定義することもできます。その場合はシリアライズ、デシリアライズを実装するだけで定義可能です。
テーブルをデプロイする
if not User.exists(): User.create_table()
テーブルが存在しない場合に新しく作成します。
削除したい場合は以下のコードで可能です。
User.delete_table()
データをPutする
foo = User('foo', '[email protected]', age=100) foo.age = 5 # この方法でも可能 foo.save()
基本的な流れはインスタンスを作成→保存といった感じです。
たくさんのデータを一度に保存したい場合はBatchWrite用のインターフェイスが用意されています。 また、トランザクション用のインターフェイスもあります。
データを取得する
user = User.get('foo', '[email protected]') print(f'name: {user.name}') # -> name: foo
キーを指定することで、データの取得が可能です。 どのAttributeをGetするかなどの指定も可能です。 クエリを使用して条件に当てはまるものをイテレーターとして受け取ることも可能です。
データを更新する
user.update(actions=[ User.age.add(1) ]) print(f'age: {user.age}') # -> age: 6
actions
にDynamoDBでの更新の操作に対応するものを入れることができます。
各AttributeにはDynamoDBのオペレータに対応するメソッドがついてます。
ここではADD
に対応するadd
を使用して1
を足しています。
他にもSET
に対応するset
などすべての操作が用意されています。
データの削除
user.delete()
delete
メソッドを呼べば該当インスタンスのアイテムを削除できます。
最後に
今まではデータクラスを定義して、それにシリアライズ等の処理を書いて、クエリを書いて、といったような処理を何度も書いてました。 プロジェクトの規模によっては抽象化することもありましたが、面倒な作業でした。 PynamoDBを使えば同様のことが少ない手間でできるので便利だと思います。 また、ローレベルのAPIも用意されているので、細かいチューニングにも対応できると思います。